package com.bc.bcupload.common;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.apache.commons.io.IOUtils;

public class ImageCuter {
	private static BufferedImage toBufferedImage(Image image) {  
        if (image instanceof BufferedImage) {  
            return (BufferedImage) image;  
        }  
        // This code ensures that all the pixels in the image are loaded  
        image = new ImageIcon(image).getImage();  
        BufferedImage bimage = null;  
        GraphicsEnvironment ge = GraphicsEnvironment  
                .getLocalGraphicsEnvironment();  
        try {  
            int transparency = Transparency.OPAQUE;  
            GraphicsDevice gs = ge.getDefaultScreenDevice();  
            GraphicsConfiguration gc = gs.getDefaultConfiguration();  
            bimage = gc.createCompatibleImage(image.getWidth(null),  
                    image.getHeight(null), transparency);  
        } catch (HeadlessException e) {  
            // The system does not have a screen  
        }  
        if (bimage == null) {  
            // Create a buffered image using the default color model  
            int type = BufferedImage.TYPE_INT_RGB;  
            bimage = new BufferedImage(image.getWidth(null),  
                    image.getHeight(null), type);  
        }  
        // Copy image to buffered image  
        Graphics g = bimage.createGraphics();  
        // Paint the image onto the buffered image  
        g.drawImage(image, 0, 0, null);  
        g.dispose();  
        return bimage;  
    }
	//一般情况下：ImageIO.read，处理图片没问题
	//但是处理ps过的图片时(ps默认保存的图片时cmyk模式的jpg图片
	//这种cmyk模式的图片是给印刷机用的，显示器无法正常处理
	//显示器只识别rgb格式
	//因此上传时可能导致报错Unsupported image type
	//或切图时导致缩略图会蒙上一层红色
	//彻底的解决方法是通过twelvemonkeys自动把cmyk转成rgb 
	//具体方法(代码还用ImageIO.read)：
	//1,maven添加twelvemonkeys的依赖
	//2,web.xml添加Listener:com.twelvemonkeys.servlet.image.IIOProviderContextListener
	public static BufferedImage getBufferedImage(String srcImageFile) throws Exception{
		//用ImageIO.read方法切图时，可能导致缩略图会蒙上一层红色
		//http://blog.csdn.net/kobejayandy/article/details/44346809
		//20171027,zhaohl
		return ImageIO.read(new File(srcImageFile));
		//Image src=Toolkit.getDefaultToolkit().getImage(srcImageFile);
		//return toBufferedImage(src);
	}
	public static BufferedImage getBufferedImage(InputStream input) throws Exception{
		//用ImageIO.read方法读取图片时，可能导致报错Unsupported image type
		//20171027,zhaohl
		//return ImageIO.read(input); 
		//用下面的方法图片本身可以正常上传，但是切图时有问题
		byte[]	imagedata=IOUtils.toByteArray(input);
		Image src=Toolkit.getDefaultToolkit().createImage(imagedata);
		return toBufferedImage(src);
	}
	/**
	 * @Description: 将srcImageFile裁剪后生成destImageFile
	 * @param srcImageFile
	 *            原始图
	 * @param destImageFile
	 *            目标图
	 * @param width
	 *            原始图预处理后width
	 * @param height
	 *            原始图预处理后height
	 * @param rect
	 *            目标图输出的格式(rect.x, rect.y, rect.width, rect.height)
	 * @throws IOException
	 * @author 窦海超
	 */
	public static void cut(String srcImageFile, String destImageFile,
			int width, int height) throws Exception {

		// 是否是旧版本
		String origPath = PropertyUtils.getProperty("IsOldCut");
		if (origPath != null && origPath != "" && origPath.equals("1")) {
			Image image= getBufferedImage(srcImageFile);
			
			Rectangle srcRect = getRect(image, width, height);
			BufferedImage bImage = makeThumbnail(image, width, height);
			saveSubImage(bImage, srcRect, new File(destImageFile));
		} else {
			ImageUtils.fromFile(new File(srcImageFile)).size(width, height)
					.rotate(0)
					// 旋转角度
					.quality(0.6f).fixedGivenSize(true).keepRatio(true)
					.bgcolor(Color.white) // 透明背景
					.toFile(new File(destImageFile));
		}
	}

	private static Rectangle getRect(Image image, int width, int height) {
		return new Rectangle(0, 0, width, height);
		// int srcWidth = image.getWidth(null);
		// int srcHeight = image.getHeight(null);
		//
		// double factorWidth = (double) width / srcWidth;
		// double factorHeight = (double) height / srcHeight;
		// double invalidFactor = Math.max(factorWidth, factorHeight);
		// Rectangle srcRect;
		// if (factorWidth > factorHeight) {
		// int validHeight = (int) (height / invalidFactor);
		// int redundantHeight = srcHeight - validHeight;
		// srcRect = new Rectangle(0, redundantHeight / 2, srcWidth,
		// validHeight);
		// } else {
		// int validWidth = (int) (width / invalidFactor);
		// int redundantWidth = srcWidth - validWidth;
		// srcRect = new Rectangle(redundantWidth / 2, 0, validWidth,
		// srcHeight);
		// }
		// return srcRect;
	}

	/**
	 * @Description: 将srcImageFile裁剪后生成destImageFile
	 * @param srcImageFile
	 *            原始图
	 * @param destImageFile
	 *            目标图
	 * @param width
	 *            原始图预处理后width
	 * @param height
	 *            原始图预处理后height
	 * @param rect
	 *            目标图输出的格式(rect.x, rect.y, rect.width, rect.height)
	 * @throws IOException
	 * @author 窦海超
	 */
	public static void cut(File srcImageFile, File destImageFile, int width,
			int height) throws Exception {
		Image image= getBufferedImage(srcImageFile.getPath());
		BufferedImage bImage = makeThumbnail(image, width, height);
		Rectangle srcRect = getRect(image, width, height);
		saveSubImage(bImage, srcRect, destImageFile);
	}

	/**
	 * 对原始图片根据(x, y, width, height) = (0, 0, width, height)进行缩放，生成BufferImage
	 * 
	 * @param img
	 * @param width
	 *            预处理后图片的宽度
	 * @param height
	 *            预处理后图片高度
	 * @return
	 * @author 窦海超
	 * @throws IOException
	 */
	private static BufferedImage makeThumbnail(Image img, int width, int height)
			throws IOException {
		BufferedImage tag = new BufferedImage(width, height, 1);
		Graphics g = tag.getGraphics();
		g.drawImage(img.getScaledInstance(width, height, 4), 0, 0, null);
		g.dispose();
		return tag;
	}

	/**
	 * 对BufferImage按照(x, y, width, height) = (subImageBounds.x,
	 * subImageBounds.y, subImageBounds.width, subImageBounds.height)进行裁剪
	 * 如果subImageBounds范围过大，则用空白填充周围的区域。
	 * 
	 * @param image
	 * @param subImageBounds
	 * @param destImageFile
	 * @throws IOException
	 * @author 窦海超
	 */
	private static void saveSubImage(BufferedImage image,
			Rectangle subImageBounds, File destImageFile) throws IOException {
		// writeHighQuality(image,destImageFile.getPath());
		String fileName = destImageFile.getName();
		String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);
		BufferedImage subImage = new BufferedImage(subImageBounds.width,
				subImageBounds.height, 1);
		Graphics g = subImage.getGraphics();

		if ((subImageBounds.width > image.getWidth())
				|| (subImageBounds.height > image.getHeight())) {
			int left = subImageBounds.x;
			int top = subImageBounds.y;
			if (image.getWidth() < subImageBounds.width)
				left = (subImageBounds.width - image.getWidth()) / 2;
			if (image.getHeight() < subImageBounds.height)
				top = (subImageBounds.height - image.getHeight()) / 2;
			g.setColor(Color.white);
			g.fillRect(0, 0, subImageBounds.width, subImageBounds.height);
			g.drawImage(image, left, top, null);
			// ImageIO.write(image, formatName, destImageFile);
		} else {
			g.drawImage(image.getSubimage(subImageBounds.x, subImageBounds.y,
					subImageBounds.width, subImageBounds.height), 0, 0, null);
		}
		g.dispose();
		ImageIO.write(subImage, formatName, destImageFile);
	}

	@SuppressWarnings("restriction")
	private static boolean writeHighQuality(BufferedImage im,
			String fileFullPath) {
		try {
			/* 输出到文件流 */
			// FileOutputStream newimage = new FileOutputStream(fileFullPath);
			// JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);
			// JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(im);
			// /* 压缩质量 */
			// jep.setQuality(1f, true);
			// encoder.encode(im, jep);
			// /*近JPEG编码*/
			// newimage.close();
			return true;
		} catch (Exception e) {
			return false;
		}
	}
}
